package cn.iocoder.yudao.module.brokerage.merchant.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.framework.business.basic.dao.query.CoreLambdaQueryWrapper;
import cn.iocoder.yudao.framework.business.basic.dao.repository.LockRedisRepository;
import cn.iocoder.yudao.framework.business.basic.pojo.vo.ShopSimpleVO;
import cn.iocoder.yudao.framework.business.basic.service.impl.AbstractService;
import cn.iocoder.yudao.framework.common.exception.Assertions;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.api.brokerage.agency.vo.AgencyBrokerageMoneyTrendVO;
import cn.iocoder.yudao.module.api.brokerage.agency.vo.AgencyBrokerageSummaryVO;
import cn.iocoder.yudao.module.api.member.agency.AgencyUserApi;
import cn.iocoder.yudao.module.api.member.agency.vo.AgencyUserVO;
import cn.iocoder.yudao.module.api.shop.info.ShopInfoApi;
import cn.iocoder.yudao.module.api.shop.info.dto.ShopInfoDTO;
import cn.iocoder.yudao.module.brokerage.merchant.dao.BrokerageMerchantMapper;
import cn.iocoder.yudao.module.brokerage.merchant.dao.BrokerageMerchantRecordMapper;
import cn.iocoder.yudao.module.brokerage.merchant.pojo.bo.BrokerageMerchantInviteSumBO;
import cn.iocoder.yudao.module.brokerage.merchant.pojo.po.AgencyMerchantDO;
import cn.iocoder.yudao.module.brokerage.merchant.pojo.vo.AppBrokerageMerchantInviteSumVO;
import cn.iocoder.yudao.module.brokerage.merchant.pojo.vo.AppBrokerageMerchantVO;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;

/**
 * 推广商家 Service 实现类
 *
 * @author 山野羡民
 */
@Slf4j
@Service
@Validated
public class AppBrokerageMerchantServiceImpl extends AbstractService<AgencyMerchantDO, AppBrokerageMerchantInviteSumVO> implements AppBrokerageMerchantService {
    private static final long TIMEOUT_MILLIS = 10 * DateUtils.SECOND_MILLIS;
    private static final String LOCK_KEY = "xianmin:member:brokerage-agency:lock:%d";

    @Resource
    private BrokerageMerchantMapper brokerageMerchantMapper;
    @Resource
    private BrokerageMerchantRecordMapper brokerageMerchantRecordMapper;

    @Resource
    private LockRedisRepository lockRedisRepository;

    @Resource
    private ShopInfoApi shopInfoApi;
    @Resource
    private AgencyUserApi agencyUserApi;

    @Override
    protected BrokerageMerchantMapper getInjectedMapper() {
        return brokerageMerchantMapper;
    }

    @Override
    public AgencyMerchantDO getOrCreate(Long shopId) {
        Assertions.notNull(shopId, "未获取到 shopId");
        return lockRedisRepository.lock(String.format(LOCK_KEY, shopId), TIMEOUT_MILLIS, () -> {
            AgencyMerchantDO entity = getInjectedMapper().findOrCreateByShopId(shopId);
            Assertions.notNull(entity, "未获取到推广商家: shopId=" + shopId);
            return entity;
        });
    }

    @Nonnull
    @Override
    public AgencyBrokerageSummaryVO getSummary(Long userId) {
        AgencyBrokerageSummaryVO respDTO = new AgencyBrokerageSummaryVO();
        Integer inviteMerchantCount = getInjectedMapper().selectInviteMerchantCount(userId);
        respDTO.setInviteMerchantCount(inviteMerchantCount == null ? 0 : inviteMerchantCount);
        Integer freezingBonusMoney = getInjectedMapper().selectFreezingBonusMoney(userId);
        respDTO.setFreezingBonusMoney(freezingBonusMoney == null ? 0 : freezingBonusMoney);
        Integer todayUnfreezeBonusMoney = getInjectedMapper().selectTodayUnfreezeBonusMoney(userId);
        respDTO.setTodayUnfreezeBonusMoney(todayUnfreezeBonusMoney == null ? 0 : todayUnfreezeBonusMoney);
        Integer totalUnfreezeBonusMoney = getInjectedMapper().selectTotalUnfreezeBonusMoney(userId);
        respDTO.setTotalUnfreezeBonusMoney(totalUnfreezeBonusMoney == null ? 0 : totalUnfreezeBonusMoney);
        return respDTO;
    }

    @Override
    public List<AgencyBrokerageMoneyTrendVO> getBonusMoneyTrend(Long userId, LocalDateTime beginTime, LocalDateTime endTime) {
        Assertions.notNull(userId, "招商人员用户编号不能为空");
        Assertions.notNull(beginTime, "开始时间不能为空");
        Assertions.notNull(endTime, "结束时间不能为空");
        List<AgencyBrokerageMoneyTrendVO> fills = getInjectedMapper().selectListByAgencyUserIdAndUnfreezeTime(userId, beginTime, endTime);
        List<AgencyBrokerageMoneyTrendVO> list = new ArrayList<>();
        for (LocalDateTime date = beginTime; date.isBefore(endTime); date = date.plusDays(1)) {
            AgencyBrokerageMoneyTrendVO respDTO = new AgencyBrokerageMoneyTrendVO();
            respDTO.setDate(date.toLocalDate());
            respDTO.setMoney(0);
            if (CollUtil.isNotEmpty(fills)) {
                for (AgencyBrokerageMoneyTrendVO it : fills) {
                    if (LocalDateTimeUtil.isSameDay(respDTO.getDate(), it.getDate())) {
                        respDTO.setMoney(it.getMoney());
                        break;
                    }
                }
            }
            list.add(respDTO);
        }
        return list;
    }

    @Override
    public PageResult<AppBrokerageMerchantInviteSumVO> getAgencyInviteSumPage(Integer pageNo, Integer pageSize, Long userId) {
        CoreLambdaQueryWrapper<AgencyMerchantDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(AgencyMerchantDO::getAgencyUserId, userId);
        PageResult<AppBrokerageMerchantInviteSumVO> page = getPage(pageNo, pageSize, wrapper);
        if (CollUtil.isEmpty(page.getList())) {
            return PageResult.empty();
        }
        Set<Long> shopIds = convertSet(page.getList(), AppBrokerageMerchantVO::getShopId);
        if (CollUtil.isEmpty(shopIds)) {
            return page;
        }
        Map<Long, ShopInfoDTO> shopInfoMap = shopInfoApi.getShopInfoMap(shopIds);
        List<BrokerageMerchantInviteSumBO> inviteSumBOList = brokerageMerchantRecordMapper.selectInviteSumByUserId(userId);
        Map<Long, BrokerageMerchantInviteSumBO> recordDOMap = convertMap(inviteSumBOList, BrokerageMerchantInviteSumBO::getSourceShopId);
        for (AppBrokerageMerchantInviteSumVO it : page.getList()) {
            ShopInfoDTO shopInfoRespDTO = shopInfoMap.getOrDefault(it.getShopId(), ShopInfoDTO.FALLBACK);
            it.setShop(BeanUtils.toBean(shopInfoRespDTO, ShopSimpleVO.class));
            BrokerageMerchantInviteSumBO merchantInviteSumBO = recordDOMap.getOrDefault(it.getShopId(), new BrokerageMerchantInviteSumBO());
            it.setTotalInviteOrderPrice(merchantInviteSumBO.getInviteOrderPrice());
            it.setTotalInviteBonusMoney(merchantInviteSumBO.getInviteBonusMoney());
        }
        return page;
    }

    @Override
    public AgencyUserVO getAgencyUserByShopId(Long shopId) {
        AgencyMerchantDO merchantDO = brokerageMerchantMapper.findOrCreateByShopId(shopId);
        if (merchantDO.getAgencyUserId() == null || merchantDO.getAgencyUserId() <= 0) {
            return null;
        }
        return agencyUserApi.getAgencyUserByUserId(merchantDO.getAgencyUserId());
    }

    @Override
    public int increaseSettlementMoney(Long shopId, Integer basePrice, Integer settlementMoney) {
        return brokerageMerchantMapper.increaseSettlementMoney(shopId, basePrice, settlementMoney);
    }

    @Override
    public int decreaseSettlementMoney(Long shopId, Integer basePrice, Integer settlementMoney) {
        return brokerageMerchantMapper.decreaseSettlementMoney(shopId, basePrice, settlementMoney);
    }

}